package com.gitee.srurl.snow.domain;

import lombok.*;

import java.io.Serial;
import java.io.Serializable;

/**
 * 雪花算法参数
 *
 * @author zxw
 * @date 2023/4/22 10:49
 */
@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class SnowflakeData implements Serializable {

    @Serial
    private static final long serialVersionUID = 2102334077425172449L;

    /**
     * 初始化时间点
     */
    private Long epoch;
    /**
     * 机器ID
     */
    private Long workerId;

    /**
     * 数据中心ID
     */
    private Long dataCenterId;

    /**
     * 允许的时钟回拨毫秒数
     */
    private Long timeOffset;

    /**
     * 当在低频模式下时，序号始终为0，导致生成ID始终为偶数<br>
     * 作为分库分表键的时候会发生数据倾斜<br>
     * 此属性用于限定一个随机上限，在不同毫秒下生成序号时，给定一个随机数，避免偶数问题。<br>
     * 注意次数必须小于{@link SnowflakeConstant#SEQUENCE_MASK}，{@code 0}表示不使用随机数。<br>
     * 这个上限不包括值本身。
     */
    private Long randomSequenceLimit;

    /**
     * 时钟回拨处理
     */
    private String backwardsHandle;

    /**
     * 最新ID时间戳 默认-1
     */
    private Long lastTimestamp;

    public static SnowflakeDataBuilder builder() {
        return new SnowflakeDataBuilder();
    }

    @Override
    @SuppressWarnings("all")
    public SnowflakeData clone() {

        return SnowflakeData.builder()
                .epoch(this.getEpoch())
                .workerId(this.getWorkerId())
                .dataCenterId(this.getDataCenterId())
                .timeOffset(this.getTimeOffset())
                .randomSequenceLimit(this.getRandomSequenceLimit())
                .backwardsHandle(this.getBackwardsHandle())
                .lastTimestamp(this.getLastTimestamp())
                .build();
    }

    @ToString
    public static class SnowflakeDataBuilder {
        private Long epoch;
        private Long workerId;
        private Long dataCenterId;
        private Long timeOffset;
        private Long randomSequenceLimit;
        private String backwardsHandle;
        private Long lastTimestamp;

        private SnowflakeDataBuilder() {
        }

        public SnowflakeDataBuilder epoch(final Long epoch) {
            this.epoch = epoch;
            return this;
        }

        public SnowflakeDataBuilder workerId(final Long workerId) {
            this.workerId = workerId;
            return this;
        }

        public SnowflakeDataBuilder dataCenterId(final Long dataCenterId) {
            this.dataCenterId = dataCenterId;
            return this;
        }

        public SnowflakeDataBuilder timeOffset(final Long timeOffset) {
            this.timeOffset = timeOffset;
            return this;
        }

        public SnowflakeDataBuilder randomSequenceLimit(final Long randomSequenceLimit) {
            this.randomSequenceLimit = randomSequenceLimit;
            return this;
        }

        public SnowflakeDataBuilder backwardsHandle(final String backwardsHandle) {
            this.backwardsHandle = backwardsHandle;
            return this;
        }

        public SnowflakeDataBuilder lastTimestamp(final long lastTimestamp) {
            this.lastTimestamp = lastTimestamp;
            return this;
        }

        public SnowflakeData build() {
            return new SnowflakeData(
                    this.epoch == null ? SnowflakeConstant.DEFAULT_TWEPOCH : this.epoch,
                    this.workerId == null ? 0 : this.workerId,
                    this.dataCenterId == null ? 0 : this.dataCenterId,
                    this.timeOffset == null ? SnowflakeConstant.DEFAULT_TIME_OFFSET : this.timeOffset,
                    this.randomSequenceLimit == null ? 0 : this.randomSequenceLimit,
                    this.backwardsHandle,
                    this.lastTimestamp == null ? -1 : this.lastTimestamp
            );
        }
    }
}
